#include <stdlib.h>

#include "library.h"

// 创建固定大小的内存池
FIXEDPOOL_API FixedPoolInterface* create_fixed_pool(const uint32_t pool_size, const uint32_t item_size) {
    if (!pool_size || !item_size) return NULL;

    // 计算需要分配的总内存大小
    const size_t interface_size = sizeof(FixedPoolInterface) + pool_size * sizeof(PItemData);
    const size_t buffer_size = pool_size * item_size;

    // 分配 FixedPoolInterface 结构体内存
    FixedPoolInterface* interface = malloc(interface_size);
    if (!interface) {
        return NULL;
    }

    // 分配 FixedPool 结构体内存
    FixedPool* pool = malloc(sizeof(FixedPool));
    if (!pool) {
        free(interface);
        return NULL;
    }

    // 分配数据缓冲区内存
    pool->buffer = malloc(buffer_size);
    if (!pool->buffer) {
        free(interface);
        free(pool);
        return NULL;
    }

    // 初始化 FixedPool
    pool->size = pool_size;
    pool->item_size = item_size;

    // 初始化 FixedPoolInterface
    interface->pool = pool;
    atomic_init(interface->pool_unused_size, pool_size);

    // 初始化未使用元素列表
    for (uint32_t i = 0; i < pool_size; i++) {
        interface->unused_item_list[i] = (PItemData)pool->buffer + item_size * i; // 位置索引从1开始
    }

    return interface;
}

// 释放固定大小的内存池
FIXEDPOOL_API void release_fixed_pool(FixedPoolInterface *interface) {
    if (!interface) return;

    if (interface->pool) {
        if (interface->pool->buffer) {
            free(interface->pool->buffer);
        }
        free(interface->pool);
    }
    free(interface);
}

// 从内存池中获取一个元素的位置
FIXEDPOOL_API PItemData get_item_in_pool(FixedPoolInterface *interface) {
    if (!interface || atomic_load_explicit(interface->pool_unused_size, memory_order_acquire) == 0) {
        return NULL;
    }

    PItemData next = interface->unused_item_list[interface->pool_unused_size - 1];
    interface->pool_unused_size -= 1;
    return next;
}

// 将元素放回内存池
FIXEDPOOL_API void put_item_in_pool(FixedPoolInterface *interface, PItemData item) {
    if (!interface) {
        return;
    }

    // 将位置添加回未使用列表
    interface->unused_item_list[interface->pool_unused_size] = item;
    interface->pool_unused_size++;
}
